package com.zjl.SpringBoot.第07章_核心部分;

import com.zjl.SpringBoot.config.MySpringBootListener;
import org.springframework.boot.BootstrapRegistryInitializer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.io.support.SpringFactoriesLoader;


/**
 * 生命周期监听
 * 场景：监听应用的生命周期，要在应用启动的某一刻执行某些操作
 * 监听器
 *      自定义SpringApplicationRunListener来监听事件
 *      编写SpringApplicationRunListener 实现类
 *
 * 自带的
 * 在 spring-boot-autoconfigure-3.2.7.jar 的  META-INF/spring.factories
 *      # Application Listeners
 *      org.springframework.context.ApplicationListener=\
 *      org.springframework.boot.autoconfigure.BackgroundPreinitializer
 * @see org.springframework.boot.autoconfigure.BackgroundPreinitializer
 *
 * -***********************************************************************
 * 自定义 监听器 {@link MySpringBootListener} //路径不能存在中文
 * ，运行的记录 就是   SpringApplication.run(xxx.class, args); 的 run 一值点击去到
 * {@link SpringApplication}
 *
 * 		Startup startup = Startup.create();
 * 		if (this.registerShutdownHook) {
 * 			SpringApplication.shutdownHook.enableShutdownHookAddition();
 *                }
 * 		DefaultBootstrapContext bootstrapContext = createBootstrapContext();//  感知引导初始化【感知特定阶段】 {@link BootstrapRegistryInitializer}
 * 		ConfigurableApplicationContext context = null;
 * 		configureHeadlessProperty();
 * 		SpringApplicationRunListeners listeners = getRunListeners(args);//获取所有 监听器 listeners
 * 	        //{@link SpringFactoriesLoader}	//在项目启动之前，先去META-INF/spring.factories读取Listener 获取监听器
 * 		//利用BootstrapContext引导整个项目启动
 * 		listeners.starting(bootstrapContext, this.mainApplicationClass);//starting：应用开始，SpringApplication的run方法一调用，只要有了BootstrapContext就执行
 * 		try {
 * 			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
 *
 * 			//准备环境变量  这里面会加载到环境变量  这里面 会执行 listeners.environmentPrepared：环境准备好（把启动参数等绑定到环境变量中），但是ioc还没有创建【调一次】
 * 			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
 *
 *           Banner printedBanner = printBanner(environment);
 * 			context = createApplicationContext();//创建 IOC 容器
 * 			context.setApplicationStartup(this.applicationStartup);
 *
 *      	//prepareContext  ioc容器创建并准备好，并关闭引导上下文，但是sources（主配置类）没加载，组件都没创建【调一次】
 *          //  contextLoaded：ioc容器加载，主配置类加载进去了，但是ioc容器还没刷新（即bean还没创建）【调一次】 =截止到这里，ioc容器里面还没创建bean=
 * 			// 加载 感知ioc容器初始化【感知特定阶段】{@link ApplicationContextInitializer}
 * 			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
 *
 *
 * 			refreshContext(context); // 启动都是使用了 {@link AbstractApplicationContext}  的 refresh() 这里完成了 spring的Bean的组件的创建
 * 			afterRefresh(context, applicationArguments);
 * 			startup.started();
 * 			if (this.logStartupInfo) {
 * 				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), startup);
 *            }
 *          //  started：ioc容器刷新了（所有bean造好了），但是runner没调用
 * 			listeners.started(context, startup.timeTakenToStarted());
 * 			callRunners(context, applicationArguments);
 *        }catch (Throwable ex){xxx}
 *        try {
 * 			    if (context.isRunning()) {
 *              //  ready：ioc容器刷新了（所有bean造好了），所有runner调用完了
 * 				listeners.ready(context, startup.ready());
 *              }
 *         }
 *
 * 也可以用 ：{@link SpringApplicationRunListener}  反点过去
 *
 *
 */
public class A_事件和监听器 {
    public static void main(String[] args) {

        SpringApplication.run(A_事件和监听器.class, args);

    }
}
